package com.tiancheng.trade.merchant.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.tiancheng.trade.commom.core.data.ApplicationInfo;
import com.tiancheng.trade.commom.core.data.PageInfo;
import com.tiancheng.trade.commom.core.enums.MerchantRegStatusEnums;
import com.tiancheng.trade.commom.core.enums.PaymentChannelEnum;
import com.tiancheng.trade.commom.core.exception.Asserts;
import com.tiancheng.trade.commom.core.exception.error.AuthErrorInfoEnum;
import com.tiancheng.trade.commom.core.exception.error.BusinessErrorInfoEnum;
import com.tiancheng.trade.commom.web.cache.AccessTokenCache;
import com.tiancheng.trade.commom.core.utils.IdWorkerUtils;
import com.tiancheng.trade.commom.core.utils.JsonUtil;
import com.tiancheng.trade.commom.web.auth.StpCustomKit;
import com.tiancheng.trade.commom.core.utils.ForestHttpUtil;
import com.tiancheng.trade.commom.web.model.OrgBusinessDTO;
import com.tiancheng.trade.commom.web.model.SubjectProfile;
import com.tiancheng.trade.commom.web.model.request.*;
import com.tiancheng.trade.commom.web.model.request.merchant.*;
import com.tiancheng.trade.commom.web.model.response.*;
import com.tiancheng.trade.merchant.channel.AbstractMerchantRegChannel;
import com.tiancheng.trade.merchant.channel.IdPhotoEnums;
import com.tiancheng.trade.merchant.channel.PayChannelFactory;
import com.tiancheng.trade.merchant.channel.bo.MerchantRegSmsSendBO;
import com.tiancheng.trade.merchant.channel.bo.MerchantRegSmsVerifyBO;
import com.tiancheng.trade.merchant.channel.handler.ums.request.UmsMerchantReqAgreementSignRequest;
import com.tiancheng.trade.merchant.channel.handler.ums.request.UmsMerchantReqCompanyAccountVerifyRequest;
import com.tiancheng.trade.merchant.channel.handler.ums.request.UmsMerchantReqRequestAccountVerifyRequest;
import com.tiancheng.trade.merchant.channel.handler.ums.request.UmsMerchantReqStatusQueryRequest;
import com.tiancheng.trade.merchant.dto.ApplyStatusUpdateDTO;
import com.tiancheng.trade.merchant.dto.MerchantRegNotifyRes;
import com.tiancheng.trade.merchant.dto.message.ChannelNotifyMessage;
import com.tiancheng.trade.merchant.dto.message.MerchantStatusMsg;
import com.tiancheng.trade.merchant.dto.requestdto.MerchantPayPivRegVO;
import com.tiancheng.trade.merchant.dto.requestdto.MerchantPayRegVO;
import com.tiancheng.trade.merchant.dto.requestdto.MinioUploadDto;
import com.tiancheng.trade.merchant.dto.responsedto.MerchantRegStatusQueryResDTO;
import com.tiancheng.trade.merchant.enums.*;
import com.tiancheng.trade.merchant.mapper.MerchantPayRegMapper;
import com.tiancheng.trade.merchant.model.*;
import com.tiancheng.trade.merchant.service.*;
import com.tiancheng.trade.merchant.util.Queue.MerchantRegisterSender;
import com.tiancheng.trade.merchant.vo.merchant.ManualSettingChannelInfoReq;
import com.tiancheng.trade.merchant.vo.merchant.QueryMerchantRegReqVO;
import com.tiancheng.trade.merchant.vo.merchant.QueryMerchantRegResVO;
import com.tiancheng.trade.merchant.vo.merchant.TradeMerchantStatusReq;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.message.BasicHeader;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @Author: kellen
 * @Description: 商户进件信息
 * @Date: create in 2024/11/19 15:25
 */
@Slf4j
@Service
public class MerchantPayRegServiceImpl extends ServiceImpl<MerchantPayRegMapper, MerchantPayReg> implements IMerchantPayRegService {

    @Resource
    private IMerchantService merchantService;
    @Resource
    private IMerchantPayRegFileService merchantPayRegFileService;
    @Resource
    private IOrgBusinessService orgBusinessService;
    @Resource
    private IUploadService uploadService;
    @Resource
    private IMerchantSettleRuleService merchantSettleRuleService;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private MerchantRegisterSender merchantRegisterSender;
    @Resource
    private IMerchantPayRegLogService merchantPayRegLogService;
    @Resource
    private IIndustryService industryService;

    private ApplicationInfo getApplication(String termNo) {
        Object extra = StpCustomKit.OPEN.getExtra("application");
        if (Objects.nonNull(extra)) {
            SubjectProfile subjectProfile = JsonUtil.fromJson(JsonUtil.toJsonString(extra), SubjectProfile.class);
            String clientId = MapUtils.getString(subjectProfile.getAttributes(), "clientId");
            // token有效期
            Integer expiresIn = MapUtils.getInteger(subjectProfile.getAttributes(), "expiresIn");
            List<ApplicationInfo> apps = new ArrayList<>();
            if (StringUtils.isNotEmpty(clientId)) {
                final Optional<List<ApplicationInfo>> orderApplication = AccessTokenCache.getOrderApplication(clientId);
                if (orderApplication.isPresent()) {
                    apps = orderApplication.get();
                } else {
                    List<OrgBusinessDTO> businessDTOS = orgBusinessService.getByClientId(clientId, termNo);
                    Asserts.isTrue(CollectionUtils.isNotEmpty(businessDTOS), "未查询到应用配置！");


                    for (OrgBusinessDTO orgBusinessDTO : businessDTOS) {
                        ApplicationInfo applicationInfo = new ApplicationInfo();
                        applicationInfo.setId(subjectProfile.getId());
                        applicationInfo.setClientId(clientId);
                        applicationInfo.setClientSecret(MapUtils.getString(subjectProfile.getAttributes(), "clientSecret"));
                        applicationInfo.setName(MapUtils.getString(subjectProfile.getAttributes(), "name"));
                        // 查询机构支付通道配置
                        applicationInfo.setIdPre(orgBusinessDTO.getIdPre());
                        applicationInfo.setTermNo(orgBusinessDTO.getTermNo());
                        applicationInfo.setBusinessCode(orgBusinessDTO.getBusinessCode());
                        applicationInfo.setBusinessName(orgBusinessDTO.getBusinessName());
                        applicationInfo.setOrganizationCode(orgBusinessDTO.getOrganizationCode());
                        applicationInfo.setOrganizationName(orgBusinessDTO.getOrganizationName());
                        applicationInfo.setOrgPaymentChannelId(orgBusinessDTO.getOrgPaymentChannelId());
                        applicationInfo.setPaymentChannelCode(orgBusinessDTO.getPaymentChannelCode());
                        apps.add(applicationInfo);
                    }
                    // token过期时间处理
                    AccessTokenCache.cacheOrderApplication(clientId, apps, expiresIn);

                }
                if (StringUtils.isNotEmpty(termNo)) {
                    return apps.stream().filter(a -> a.getTermNo().equals(termNo)).findFirst().get();
                }
                return apps.get(0);
            }
        }
        AuthErrorInfoEnum.AUTH_TOKEN_ERROR.assertFail();
        return null;
    }


    @Override
    public MerchantPayRegFileResVO upload(MultipartFile file, Integer regMode, String termNo) {
        final ApplicationInfo application = getApplication(termNo);

        BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(Objects.nonNull(application), "应用未被授权交易！");
        final List<OrgBusiness> orgBusinesses = orgBusinessService.list(new LambdaQueryWrapper<OrgBusiness>().eq(OrgBusiness::getClientId, application.getClientId()).eq(OrgBusiness::getOrgPaymentChannelId, application.getOrgPaymentChannelId()));
        BusinessErrorInfoEnum.MERCHANT_REG_BUSINESS_ERROR.assertNotEmpty(orgBusinesses);
        // 上传文件到文件中心
        final MinioUploadDto upload = uploadService.upload(file);
        BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(Objects.nonNull(upload), "上传文件失败！");
        // 上传文件到银联
        final AbstractMerchantRegChannel merchantRegChannel = getPayChannel(orgBusinesses.get(0).getPaymentChannelCode());
        final MerchantPayRegFile merchantPayRegFile = merchantRegChannel.upload(file, regMode, upload);

        // 保存
        merchantPayRegFile.setFileId(upload.getFileId());
        merchantPayRegFile.setInnerFilePath(upload.getUrl());
        merchantPayRegFile.setOrgPaymentChannelId(application.getOrgPaymentChannelId());
        merchantPayRegFile.setIsDelete(0);
        merchantPayRegFile.setCreatedDt(LocalDateTime.now());
        merchantPayRegFileService.save(merchantPayRegFile);

        final MerchantPayRegFileResVO merchantPayRegFileResVO = new MerchantPayRegFileResVO();
        merchantPayRegFileResVO.setFileId(merchantPayRegFile.getId().toString());
        merchantPayRegFileResVO.setFilePath(merchantPayRegFile.getFilePath());
        merchantPayRegFileResVO.setInnerFilePath(merchantPayRegFile.getInnerFilePath());
        merchantPayRegFileResVO.setFileSize(merchantPayRegFile.getFileSize());
        merchantPayRegFileResVO.setFileType(merchantPayRegFile.getFileType());
        return merchantPayRegFileResVO;
    }

    @Override
    public MerchantPayRegFileResVO upload(MultipartFile file, String documentType, Integer regMode, String termNo) {
        final ApplicationInfo application = getApplication(termNo);
        Optional<IdPhotoEnums> idPhotoEnums = IdPhotoEnums.getByCode(documentType);
        if (StringUtils.isNotEmpty(documentType)) {
            Asserts.isTrue(idPhotoEnums.isPresent(), "不支持的证件照类型！");
        }
        BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(Objects.nonNull(application), "应用未被授权交易！");
        final List<OrgBusiness> orgBusinesses = orgBusinessService.list(new LambdaQueryWrapper<OrgBusiness>().eq(OrgBusiness::getClientId, application.getClientId()).eq(OrgBusiness::getOrgPaymentChannelId, application.getOrgPaymentChannelId()));
        BusinessErrorInfoEnum.MERCHANT_REG_BUSINESS_ERROR.assertNotEmpty(orgBusinesses);
        // 上传文件到银联
        final AbstractMerchantRegChannel merchantRegChannel = getPayChannel(orgBusinesses.get(0).getPaymentChannelCode());

        // 上传文件到文件中心
        final MinioUploadDto upload = uploadService.upload(file);
        BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(Objects.nonNull(upload), "上传文件失败！");

        final MerchantPayRegFile merchantPayRegFile = merchantRegChannel.upload(file, regMode, upload);

        // 保存
        merchantPayRegFile.setDocumentType(documentType);
        idPhotoEnums.ifPresent(photoEnums -> merchantPayRegFile.setDocumentName(photoEnums.getName()));
        merchantPayRegFile.setFileId(upload.getFileId());
        merchantPayRegFile.setInnerFilePath(upload.getUrl());
        merchantPayRegFile.setOrgPaymentChannelId(application.getOrgPaymentChannelId());
        merchantPayRegFile.setIsDelete(0);
        merchantPayRegFile.setCreatedDt(LocalDateTime.now());
        merchantPayRegFile.setDocumentName(idPhotoEnums.get().getName());
        merchantPayRegFileService.save(merchantPayRegFile);

        final MerchantPayRegFileResVO merchantPayRegFileResVO = new MerchantPayRegFileResVO();
        merchantPayRegFileResVO.setFileId(merchantPayRegFile.getId().toString());
        merchantPayRegFileResVO.setFilePath(merchantPayRegFile.getFilePath());
        merchantPayRegFileResVO.setInnerFilePath(merchantPayRegFile.getInnerFilePath());
        merchantPayRegFileResVO.setFileSize(merchantPayRegFile.getFileSize());
        merchantPayRegFileResVO.setFileType(merchantPayRegFile.getFileType());
        merchantPayRegFileResVO.setFileName(merchantPayRegFile.getDocumentName());
        return merchantPayRegFileResVO;
    }

    @Override
    public MerchantRegAllInfoNewRes registerMerchantNew(RegisterMerchantReqNewVO merchantReqVO) {
        if (Objects.nonNull(merchantReqVO.getRegMode())) {
            Asserts.isTrue(merchantReqVO.getRegMode() <= 1, "不支持的进件模式，当前支持：0-人工进件，1-自助进件");
        }
        final ApplicationInfo application = getApplication(merchantReqVO.getTermNo());
        merchantReqVO.setOrgPaymentChannelId(application.getOrgPaymentChannelId());
        merchantReqVO.setClientId(application.getClientId());

        final Optional<MerchantTypeEnums> merchantTypeEnums = MerchantTypeEnums.getByCode(merchantReqVO.getMerchantType());
        BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(merchantTypeEnums.isPresent(), "不支持的商户类型！");
        final List<OrgBusiness> orgBusinesses = orgBusinessService.list(new LambdaQueryWrapper<OrgBusiness>().eq(OrgBusiness::getClientId, merchantReqVO.getClientId()).eq(OrgBusiness::getOrgPaymentChannelId, merchantReqVO.getOrgPaymentChannelId()));
        BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(CollectionUtils.isNotEmpty(orgBusinesses), "平台支付配置异常");
        List<Merchant> merchants = null;
        // 判断是否重复注册
        if (merchantTypeEnums.get() != MerchantTypeEnums.xiao_wei) {
            // 不是小微商户
            BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(StringUtils.isNotEmpty(merchantReqVO.getShopLic()));
            // 根据社会信用代码判断重复
            merchants = merchantService.list(new LambdaQueryWrapper<Merchant>().eq(Merchant::getShopLic, merchantReqVO.getShopLic()));
        } else {
            // 小微商户
            BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(Objects.nonNull(merchantReqVO.getLegalSex()) && Objects.nonNull(merchantReqVO.getLegalOccupation()));
            merchants = merchantService.list(new LambdaQueryWrapper<Merchant>().eq(Merchant::getLegalIdcardNo, merchantReqVO.getLegalIdcardNo()));
        }
        // 4、获取证件照文件列表
        final List<MerchantPayRegFile> fileList = getFileListNew(merchantReqVO.getFileIds());
        checkCertificateFile(merchantReqVO, merchantTypeEnums.get(), fileList);
        AtomicReference<MerchantPayReg> merchantPayReg = new AtomicReference<>();
        AtomicReference<Long> tradeMerchantPayRegId = new AtomicReference<>();
        if (CollectionUtils.isNotEmpty(merchants)) {
            // 已经注册过商户
            // 首先查询是否进件了
            if (Objects.nonNull(merchantReqVO.getTradeMerchantPayRegId())) {
                MerchantPayReg deleteEntity = new MerchantPayReg();
                deleteEntity.setId(merchantReqVO.getTradeMerchantPayRegId());
                deleteEntity.setIsDelete(0);
                deleteEntity.setLastUpdDt(LocalDateTime.now());
                this.updateById(deleteEntity);
            }
            List<MerchantPayReg> merchantPayRegs = this.list(new LambdaQueryWrapper<MerchantPayReg>().eq(MerchantPayReg::getMerchantCode, merchants.get(0).getMerchantCode()).eq(MerchantPayReg::getOrgPaymentChannelId, merchantReqVO.getOrgPaymentChannelId()).eq(MerchantPayReg::getIsDelete, 0));

            if (CollectionUtils.isNotEmpty(merchantPayRegs)) {
                // 已经在该渠道进件过，根据状态进行更新或者直接返回
                Asserts.isTrue(merchantPayRegs.stream().noneMatch(m -> m.getApplyStatus().equals(Integer.parseInt(MerchantApplyStatusEnums.success.getCode()))), "商户已有进件记录，不能重复提交");
            }
            // 开始进件流程
            List<Merchant> finalMerchants = merchants;
            Boolean isSc = transactionTemplate.execute(transactionStatus -> {
                try {
                    // 1、保存商户进件信息
                    merchantPayReg.set(saveMerchantPayRegNew(finalMerchants.get(0), merchantReqVO, application));
                    tradeMerchantPayRegId.set(merchantPayReg.get().getId());
                    // 2、保存清分规则信息
                    saveRuleNew(merchantReqVO, merchantPayReg.get());
                    // 3、获取证件照文件列表
                    final AbstractMerchantRegChannel merchantRegChannel = getPayChannel(orgBusinesses.get(0).getPaymentChannelCode());
                    // 4、调用进件接口
                    final MerchantPayReg merchantPayReg1 = merchantRegChannel.complexUpload(application, getMerchantPayRegVO(merchantPayReg.get(), finalMerchants.get(0), fileList));
                    // 5、更新进件表
                    final MerchantPayReg updateMerchant = new MerchantPayReg();
                    updateMerchant.setId(merchantPayReg.get().getId());
                    updateMerchant.setChannelRegId(merchantPayReg1.getChannelRegId());
                    updateMerchant.setRegCurrentFlows(MerchantRegStatusEnums.INIT.getCode());
                    updateMerchant.setRegNextFlows(merchantRegChannel.nextFlow(MerchantRegStatusEnums.INIT, merchantTypeEnums.get()).getCode());
                    if (StringUtils.isNotEmpty(merchantPayReg1.getChannelMerNo())) {
                        // 返回了渠道支付商户号
                        updateMerchant.setChannelMerNo(merchantPayReg1.getChannelMerNo());
                    }
                    if (StringUtils.isNotEmpty(merchantPayReg1.getChannelMerNo())) {
                        // 返回了渠道分账商户号
                        updateMerchant.setCompanyNo(merchantPayReg1.getCompanyNo());
                    }
                    this.updateById(updateMerchant);
                    fileList.stream().peek(f -> f.setMerchantPayRegId(merchantPayReg.get().getId()));
                    merchantPayRegFileService.updateBatchById(fileList);
                    return true;
                } catch (Exception e) {
                    transactionStatus.setRollbackOnly();
                    throw e;
                }
            });
            BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(null != isSc && isSc, "进件失败！");
        } else {
            Boolean isSc = transactionTemplate.execute(transactionStatus -> {
                try {
                    // 更新退款流水状态
                    // 1、商户没有注册过、注册商户&&调用渠道进件接口
                    final Merchant merchant = new Merchant();
                    merchant.setOrganizationCode(orgBusinesses.get(0).getOrganizationCode());
                    merchant.setMerchantName(merchantReqVO.getMerchantName());
                    merchant.setState(1);
                    merchant.setPhone(merchantReqVO.getLegalMobile());
                    merchant.setScene("1");
                    merchant.setRevenueType("ALL");

                    merchant.setMerchantType(merchantTypeEnums.get().getCode().toString());
                    merchant.setLegalName(merchantReqVO.getLegalName());
                    merchant.setLegalIdcardNo(merchantReqVO.getLegalIdcardNo());
                    merchant.setLegalMobile(merchantReqVO.getLegalMobile());
                    merchant.setLegalSex(merchantReqVO.getLegalSex());
                    merchant.setLegalCardBeginDate(merchantReqVO.getLegalCardBeginDate());
                    merchant.setLegalCardDeadline(merchantReqVO.getLegalCardDeadline());
                    merchant.setLegalSex(merchantReqVO.getLegalSex());
                    merchant.setLegalOccupation(null == merchantReqVO.getLegalOccupation() ? 0 : merchantReqVO.getLegalOccupation());
                    merchant.setLegalAddress(merchantReqVO.getLegalAddress());
                    merchant.setShopLic(merchantReqVO.getShopLic());
                    merchant.setRemark(merchantReqVO.getShopAddress());
                    merchantService.add(merchant);

                    // 2、保存商户进件信息
                    merchantPayReg.set(saveMerchantPayRegNew(merchant, merchantReqVO, application));
                    tradeMerchantPayRegId.set(merchantPayReg.get().getId());
                    // 3、保存清分规则信息
                    saveRuleNew(merchantReqVO, merchantPayReg.get());
                    final AbstractMerchantRegChannel merchantRegChannel = getPayChannel(orgBusinesses.get(0).getPaymentChannelCode());
                    // 5、调用进件接口
                    final MerchantPayReg merchantPayReg1 = merchantRegChannel.complexUpload(application, getMerchantPayRegVO(merchantPayReg.get(), merchant, fileList));
                    // 6、更新进件表
                    final MerchantPayReg updateMerchant = new MerchantPayReg();
                    updateMerchant.setId(merchantPayReg.get().getId());
                    updateMerchant.setChannelRegId(merchantPayReg1.getChannelRegId());
                    updateMerchant.setRegCurrentFlows(MerchantRegStatusEnums.INIT.getCode());
                    updateMerchant.setRegNextFlows(merchantRegChannel.nextFlow(MerchantRegStatusEnums.INIT, merchantTypeEnums.get()).getCode());
                    this.updateById(updateMerchant);
                    fileList.stream().peek(f -> f.setMerchantPayRegId(merchantPayReg.get().getId()));
                    merchantPayRegFileService.updateBatchById(fileList);
                    return true;
                } catch (Exception e) {
                    transactionStatus.setRollbackOnly();
                    throw e;
                }
            });
            BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(null != isSc && isSc, "进件失败！");
        }

        MerchantPayReg mpr = merchantPayReg.get();
        merchantPayRegLogService.saveFlowLog(mpr.getId(), MerchantRegStatusEnums.INIT, MerchantRegStatusEnums.INIT, 1);

        // 模拟延迟回调
        // 延迟一分钟，模拟进件成功回调
        /*if (null != mpr) {
            MerchantStatusMsg message = new MerchantStatusMsg();
            message.setMerchantPayRegId(mpr.getId());
            message.setApplyStatus(mpr.getApplyStatus());
            message.setApplySubStatus(mpr.getApplySubStatus());
            message.setMessageTime(LocalDateTime.now());
            message.setMerchantCode(mpr.getMerchantCode());
            message.setRegCode(mpr.getRegCode());
            merchantRegisterSender.sendMessage(message, 60 * 1000);
        }*/

        // 查询一把
        return queryMerchantRegAllInfoResNew(tradeMerchantPayRegId.get());
    }

    /**
     * 校验商户证件信息
     *
     * @param params
     * @param merchantTypeEnums
     * @param files
     */
    private void checkCertificateFile(RegisterMerchantReqNewVO params, MerchantTypeEnums merchantTypeEnums, List<MerchantPayRegFile> files) {
        if (merchantTypeEnums.getCode().equals(3)) {
            idFileCheck(Arrays.asList(IdPhotoEnums.fr_sfz, IdPhotoEnums.fr_sfz_fm), files);
            // 小微商户
            Asserts.isTrue(fileIsUpload(IdPhotoEnums.fzzmcl, files) || fileIsUpload(IdPhotoEnums.fzzmcl1, files), "小微商户至少上传一张辅助材料！");
        } else {
            // 企业、个体户
            idFileCheck(Arrays.asList(IdPhotoEnums.fr_sfz, IdPhotoEnums.fr_sfz_fm, IdPhotoEnums.sh_yyzz), files);
            Asserts.isTrue(StringUtils.isNotEmpty(params.getShopLicenseBeginDate()) && StringUtils.isNotEmpty(params.getShopLicenseEndDate()), "企业、机关单位、个体商户营业执照有效期必传！");
            if (params.getMerchantType().equals(1)) {
                Asserts.isTrue(fileIsUpload(IdPhotoEnums.khxkz, files), "企业商户必须上传开户许可证！");
                Asserts.isTrue(fileIsUpload(IdPhotoEnums.wzapp, files), "企业商户必须上传至少一张网站或APP截图！");
            }
        }
    }

    private void idFileCheck(List<IdPhotoEnums> enums, List<MerchantPayRegFile> files) {
        for (IdPhotoEnums anEnum : enums) {
            Asserts.isTrue(fileIsUpload(anEnum, files), "请上传" + anEnum.getName() + "!");
        }
    }

    private boolean fileIsUpload(IdPhotoEnums anEnum, List<MerchantPayRegFile> files) {
        return files.stream().anyMatch(f -> StringUtils.isNotEmpty(f.getDocumentType()) && anEnum.getCode().equals(f.getDocumentType()));
    }

    private MerchantRegAllInfoRes queryMerchantRegAllInfoRes(Long merchantPayRegId) {
        final MerchantRegAllInfoRes result = new MerchantRegAllInfoRes();
        // 商户进件信息
        final MerchantPayReg merchantPayReg = this.getById(merchantPayRegId);
        // 商户信息
        final Merchant merchant = merchantService.getOne(new LambdaQueryWrapper<Merchant>().eq(Merchant::getMerchantCode, merchantPayReg.getMerchantCode()));
        // 进件证件照信息
        final List<MerchantPayRegFile> fileList = merchantPayRegFileService.list(new LambdaQueryWrapper<MerchantPayRegFile>().eq(MerchantPayRegFile::getMerchantPayRegId, merchantPayReg.getId()).eq(MerchantPayRegFile::getIsDelete, 0));
        result.setOrgPaymentChannelId(merchantPayReg.getOrgPaymentChannelId());
        result.setTradeMerchantCode(merchantPayReg.getMerchantCode());
        result.setTradeMerchantPayRegId(merchantPayReg.getOrgPaymentChannelId());
        result.setMerchantType(Integer.parseInt(merchant.getMerchantType()));
        result.setMerchantName(merchant.getMerchantName());
        result.setShopLic(merchant.getShopLic());
        result.setShopProvinceId(merchantPayReg.getShopProvinceId());
        result.setShopCityId(merchantPayReg.getShopCityId());
        result.setShopCountryId(merchantPayReg.getShopCountryId());
        result.setShopAddress(merchant.getRemark());
        result.setShopLicenseBeginDate(merchantPayReg.getShopLicenseBeginDate());
        result.setShopLicenseEndDate(merchantPayReg.getShopLicenseEndDate());
        result.setLegalName(merchant.getLegalName());
        result.setLegalIdcardNo(merchant.getLegalIdcardNo());
        result.setLegalSex(merchant.getLegalSex());
        result.setLegalMobile(merchant.getLegalMobile());
        result.setLegalCardBeginDate(merchant.getLegalCardBeginDate());
        result.setLegalCardDeadline(merchant.getLegalCardDeadline());
        result.setLegalAddress(merchant.getLegalAddress());
        // 营业执照
        result.setBusinessLicense(getFileUrlByType(fileList, IdPhotoEnums.sh_yyzz));
        // 法人身份证-正面
        result.setIdCardPositive(getFileUrlByType(fileList, IdPhotoEnums.fr_sfz));
        // 法人身份证-背面
        result.setIdCardBack(getFileUrlByType(fileList, IdPhotoEnums.fr_sfz_fm));
        result.setLegalOccupation(merchant.getLegalOccupation());
        result.setBankNo(merchantPayReg.getBankNo());
        result.setBankAcctType(merchantPayReg.getBankAcctType());
        result.setBankAcctName(merchantPayReg.getBankAcctName());
        result.setBankAcctPhone(merchantPayReg.getBankAcctPhone());
        result.setBankCardPositiveUrl(getFileUrlByType(fileList, IdPhotoEnums.yhk_zmz));
        result.setBankCardBackUrl(getFileUrlByType(fileList, IdPhotoEnums.yhk_bmz));
        result.setAccountOpeningLicense(getFileUrlByType(fileList, IdPhotoEnums.khxkz));
        result.setAuxiliaryMaterialsImg(getFileUrlByType(fileList, IdPhotoEnums.fzzmcl));
        result.setAuxiliaryMaterialsImg1(getFileUrlByType(fileList, IdPhotoEnums.fzzmcl1));
        result.setTradeMerchantPayRegId(merchantPayReg.getId());


        List<MerchantPayRegFileResVO> files = fileList.stream().map(item -> {
            MerchantPayRegFileResVO vo = new MerchantPayRegFileResVO();
            vo.setId(item.getId());
            vo.setFileId(item.getFileId());
            vo.setFilePath(item.getFilePath());
            vo.setInnerFilePath(item.getInnerFilePath());
            vo.setFileSize(item.getFileSize());
            vo.setFileName(item.getDocumentName());
            vo.setDocumentType(item.getDocumentType());
            vo.setFileType(item.getFileType());
            return vo;
        }).toList();
        result.setFiles(files);
        // 查询清分信息
        final MerchantSettleRule merchantSettleRule = merchantSettleRuleService.currentRule(merchant.getMerchantCode(), merchantPayReg.getOrgPaymentChannelId());
        if (!Objects.isNull(merchantSettleRule)) {
            result.setPlatformPercent(merchantSettleRule.getPlatformPercent());
            result.setCycleType(merchantSettleRule.getCycleValue());
            result.setClearRemark(merchantSettleRule.getRemark());
        }
        return result;
    }

    private MerchantRegAllInfoNewRes queryMerchantRegAllInfoResNew(Long merchantPayRegId) {
        final MerchantRegAllInfoNewRes result = new MerchantRegAllInfoNewRes();
        // 商户进件信息
        final MerchantPayReg merchantPayReg = this.getById(merchantPayRegId);
        // 商户信息
        final Merchant merchant = merchantService.getOne(new LambdaQueryWrapper<Merchant>().eq(Merchant::getMerchantCode, merchantPayReg.getMerchantCode()));
        // 进件证件照信息
        final List<MerchantPayRegFile> fileList = merchantPayRegFileService.list(new LambdaQueryWrapper<MerchantPayRegFile>().eq(MerchantPayRegFile::getMerchantPayRegId, merchantPayReg.getId()).eq(MerchantPayRegFile::getIsDelete, 0));
        result.setOrgPaymentChannelId(merchantPayReg.getOrgPaymentChannelId());
        result.setTradeMerchantCode(merchantPayReg.getMerchantCode());
        result.setTradeMerchantPayRegId(merchantPayReg.getId());
        result.setMerchantType(Integer.parseInt(merchant.getMerchantType()));
        result.setMerchantName(merchant.getMerchantName());
        result.setShopLic(merchant.getShopLic());
        result.setShopProvinceId(merchantPayReg.getShopProvinceId());
        result.setShopCityId(merchantPayReg.getShopCityId());
        result.setShopCountryId(merchantPayReg.getShopCountryId());
        result.setShopAddress(merchant.getRemark());
        result.setShopLicenseBeginDate(merchantPayReg.getShopLicenseBeginDate());
        result.setShopLicenseEndDate(merchantPayReg.getShopLicenseEndDate());
        result.setLegalName(merchant.getLegalName());
        result.setLegalIdcardNo(merchant.getLegalIdcardNo());
        result.setLegalSex(merchant.getLegalSex());
        result.setLegalMobile(merchant.getLegalMobile());
        result.setLegalCardBeginDate(merchant.getLegalCardBeginDate());
        result.setLegalCardDeadline(merchant.getLegalCardDeadline());
        result.setLegalAddress(merchant.getLegalAddress());
        result.setLegalOccupation(merchant.getLegalOccupation());
        result.setBankNo(merchantPayReg.getBankNo());
        result.setBankAcctType(merchantPayReg.getBankAcctType());
        result.setBankAcctName(merchantPayReg.getBankAcctName());
        result.setBankAcctPhone(merchantPayReg.getBankAcctPhone());
        result.setTradeMerchantPayRegId(merchantPayReg.getId());
        result.setRegCurrentFlows(merchantPayReg.getRegCurrentFlows());
        result.setRegNextFlows(merchantPayReg.getRegNextFlows());
        // 查询清分信息
        final MerchantSettleRule merchantSettleRule = merchantSettleRuleService.currentRule(merchant.getMerchantCode(), merchantPayReg.getOrgPaymentChannelId());
        if (!Objects.isNull(merchantSettleRule)) {
            result.setPlatformPercent(merchantSettleRule.getPlatformPercent());
            result.setCycleType(merchantSettleRule.getCycleValue());
            result.setClearRemark(merchantSettleRule.getRemark());
        }
        if (CollectionUtils.isNotEmpty(fileList)) {
            List<MerchantPayRegFileResVO> payRegFileResVOS = fileList.stream().map(f -> {
                MerchantPayRegFileResVO item = new MerchantPayRegFileResVO();
                item.setFileId(f.getFileId());
                item.setFilePath(f.getInnerFilePath());
                item.setFileName(f.getDocumentName());
                item.setDocumentType(f.getDocumentType());
                item.setFileType(f.getFileType());
                item.setFileSize(f.getFileSize());
                item.setInnerFilePath(f.getInnerFilePath());
                return item;
            }).toList();
            result.setFileList(payRegFileResVOS);
        }
        return result;
    }

    private String getFileUrlByType(List<MerchantPayRegFile> fileList, IdPhotoEnums enums) {
        if (CollectionUtils.isNotEmpty(fileList)) {
            return fileList.stream().filter(f -> StringUtils.isNotEmpty(f.getDocumentType()) && f.getDocumentType().equals(enums.getCode())).map(MerchantPayRegFile::getInnerFilePath).findAny().orElse("");
        }
        return null;
    }


    /**
     * 文件列表
     *
     * @param fileIds
     * @return
     */
    private List<MerchantPayRegFile> getFileListNew(List<String> fileIds) {
        if (CollectionUtils.isEmpty(fileIds)) {
            return Collections.emptyList();
        }
        return merchantPayRegFileService.queryByIds(fileIds);
    }


    /**
     * 保存商户进件记录
     *
     * @param merchant      商户信息
     * @param merchantReqVO 进件信息
     * @param application   应用信息
     * @return
     */
    private MerchantPayReg saveMerchantPayRegNew(Merchant merchant, RegisterMerchantReqNewVO merchantReqVO, ApplicationInfo application) {
        final MerchantPayReg merchantPayReg = new MerchantPayReg();
        merchantPayReg.setRegCode(IdWorkerUtils.getInstance().buildPartNumber());
        merchantPayReg.setMerchantCode(merchant.getMerchantCode());
        merchantPayReg.setOrgPaymentChannelId(application.getOrgPaymentChannelId());
        merchantPayReg.setShopName(merchant.getMerchantName());
        merchantPayReg.setBankNo(merchantReqVO.getBankNo());
        merchantPayReg.setBankAcctType(merchantReqVO.getBankAcctType());
        merchantPayReg.setBankAcctNo(merchantReqVO.getBankAcctNo());
        merchantPayReg.setBankAcctName(merchantReqVO.getBankAcctName());
        merchantPayReg.setShopProvinceId(merchantReqVO.getShopProvinceId());
        merchantPayReg.setShopCityId(merchantReqVO.getShopCityId());
        merchantPayReg.setShopCountryId(merchantReqVO.getShopCountryId());
        merchantPayReg.setIsChain(0);
        merchantPayReg.setApplyStatus(0);
        merchantPayReg.setOrgSubMerchant(2);
        merchantPayReg.setIsDelete(0);
        merchantPayReg.setRegCurrentFlows(MerchantRegStatusEnums.INIT.getCode());
        merchantPayReg.setRegNextFlows(getPayChannel(application.getPaymentChannelCode()).nextFlow(MerchantRegStatusEnums.INIT, MerchantTypeEnums.getByCode(Integer.valueOf(merchant.getMerchantType())).get()).getCode());
        merchantPayReg.setShopLicenseBeginDate(merchantReqVO.getShopLicenseBeginDate());
        merchantPayReg.setShopLicenseEndDate(merchantReqVO.getShopLicenseEndDate());
        merchantPayReg.setNotifyUrl(merchantReqVO.getNotifyUrl());
        merchantPayReg.setRegMode(1);
        merchantPayReg.setMccCode(merchantReqVO.getMccCode());
        merchantPayReg.setCreatedDt(LocalDateTime.now());
        merchantReqVO.setRegMode(Objects.isNull(merchantReqVO.getRegMode()) ? 1 : merchantReqVO.getRegMode());
        this.save(merchantPayReg);
        return merchantPayReg;
    }


    private void saveRuleNew(RegisterMerchantReqNewVO merchantReqVO, MerchantPayReg merchantPayReg) {
        final MerchantSettleRule rule = new MerchantSettleRule();
        rule.setMerchantCode(merchantPayReg.getMerchantCode());
        rule.setOrgPaymentChannelId(merchantPayReg.getOrgPaymentChannelId());
        rule.setCycleType(merchantReqVO.getCycleType());
        rule.setCycleValue(merchantReqVO.getCycleValue().toString());
        rule.setRemark(merchantReqVO.getClearRemark());
        rule.setPlatformPercent(merchantReqVO.getPlatformPercent());
        merchantSettleRuleService.addRule(rule);
    }

    private MerchantPayRegVO getMerchantPayRegVO(MerchantPayReg merchantPayReg, Merchant merchant, List<MerchantPayRegFile> fileList) {
        MerchantPayRegVO regVO = new MerchantPayRegVO();
        regVO.setAccesserUserId(merchantPayReg.getMerchantCode());
        regVO.setRegMerType(getMerType(merchant.getMerchantType()));
        regVO.setLegalName(merchant.getLegalName());
        regVO.setLegalMobile(merchant.getLegalMobile());
        regVO.setLegalEmail(merchant.getLegalEmail());
        regVO.setLegalIdcardNo(merchant.getLegalIdcardNo());
        regVO.setLegalCardBeginDate(merchant.getLegalCardBeginDate());
        regVO.setLegalCardDeadline(merchant.getLegalCardDeadline());
        regVO.setLegalOccupation(merchant.getLegalOccupation());
        regVO.setLegalmanHomeAddr(merchant.getLegalAddress());
        regVO.setShopName(merchant.getMerchantName());
        regVO.setBankNo(merchantPayReg.getBankNo());
        regVO.setBankAcctType(merchantPayReg.getBankAcctType());
        regVO.setLegalSex(merchant.getLegalSex());
        regVO.setBankAcctNo(merchantPayReg.getBankAcctNo());
        // TODO 开户帐号名称，对公账户填写公司名称，需与营业执照名称保持一致 个人账户填写法人姓名
        if (merchant.getMerchantType().equals(MerchantTypeEnums.xiao_wei.getCode().toString())) {
            regVO.setBankAcctName(merchant.getLegalName());
        } else {
            regVO.setBankAcctName(merchant.getMerchantName());
            // 小微商户不上传执照号
            regVO.setShopLic(merchant.getShopLic());
            // 控股股东姓名
            regVO.setShareholderName(merchant.getLegalName());
            regVO.setShareholderCertno(merchant.getLegalIdcardNo());
            regVO.setShareholderCertType("1");
            regVO.setShareholderCertBeginDate(regVO.getLegalCardBeginDate());
            regVO.setShareholderCertExpire(regVO.getLegalCardDeadline());
            regVO.setShareholderHomeAddr(regVO.getLegalmanHomeAddr());
        }
        regVO.setShopLicenseBeginDate(merchantPayReg.getShopLicenseBeginDate());
        regVO.setShopLicenseEndDate(merchantPayReg.getShopLicenseEndDate());
        regVO.setShopProvinceId(merchantPayReg.getShopProvinceId());
        regVO.setShopCityId(merchantPayReg.getShopCityId());
        regVO.setShopCountryId(merchantPayReg.getShopCountryId());

        regVO.setShopAddrExt(merchant.getRemark());
        regVO.setMccCode(StringUtils.isNotEmpty(merchantPayReg.getMccCode()) ? merchantPayReg.getMccCode() : "1");
        List<MerchantPayRegVO.MerchantPayRegProduct> product = new ArrayList<>();
        final MerchantPayRegVO.MerchantPayRegProduct regProduct = new MerchantPayRegVO.MerchantPayRegProduct();
        regProduct.setProductId("8");
        product.add(regProduct);
        /*final MerchantPayRegVO.MerchantPayRegProduct regProductIN4 = new MerchantPayRegVO.MerchantPayRegProduct();
        regProductIN4.setProductId("9");
        product.add(regProductIN4);*/
        regVO.setProduct(product);
        final List<MerchantPayPivRegVO> picList = new ArrayList<>();
        for (MerchantPayRegFile merchantPayRegFile : fileList) {
            final MerchantPayPivRegVO picFile = new MerchantPayPivRegVO();
            picFile.setDocumentType(merchantPayRegFile.getDocumentType());
            picFile.setDocumentName(merchantPayRegFile.getDocumentName());
            picFile.setFilePath(merchantPayRegFile.getFilePath());
            picFile.setFileSize(merchantPayRegFile.getFileSize());
            picList.add(picFile);
        }
        regVO.setPicList(picList);
        return regVO;
    }

    /**
     * 获取银行商户类型
     *
     * @param merchantType
     * @return
     */
    private String getMerType(String merchantType) {
        Optional<MerchantTypeEnums> merchantTypeEnums = MerchantTypeEnums.getByCode(Integer.valueOf(merchantType));
        Asserts.isTrue(merchantTypeEnums.isPresent(), "不支持的商户类型！");
        return merchantTypeEnums.get().getOutCode();
    }

    @Override
    public String regionData(String dataType, String termNo) {
        final ApplicationInfo application = getApplication(termNo);
        final AbstractMerchantRegChannel merchantRegChannel = getPayChannel(application.getPaymentChannelCode());
        return merchantRegChannel.queryRegin(dataType);
    }

    @Override
    public List<MerchantBranchBankListResVO> branchBankList(MerchantBranchBankListReqVO merchantBranchBankListReqVO) {
        final ApplicationInfo application = getApplication(merchantBranchBankListReqVO.getTermNo());

        final AbstractMerchantRegChannel merchantRegChannel = getPayChannel(application.getPaymentChannelCode());
        final List<MerchantBranchBankListResVO> bankList = merchantRegChannel.branchBankList(merchantBranchBankListReqVO);
        return bankList;
    }

    /**
     * 发起对公账户验证交易
     * 接入平台调用档案资料上传接口后，若bank_acct_type为公司账户
     *
     * @param param
     */
    @Override
    public RequestAccountVerifyResVO requestAccountVerify(RequestAccountVerifyRequest param) {
        final ApplicationInfo application = getApplication(param.getTermNo());
        final AbstractMerchantRegChannel merchantRegChannel = getPayChannel(application.getPaymentChannelCode());
        final UmsMerchantReqRequestAccountVerifyRequest accountVerifyRequest = new UmsMerchantReqRequestAccountVerifyRequest();
        MerchantPayReg payReg = this.getById(param.getTradeMerchantPayRegId());
        Asserts.isTrue(null != payReg && Objects.nonNull(payReg.getId()), "商户进件记录不存在！");
        final Merchant merchant = merchantService.getOne(new LambdaQueryWrapper<Merchant>().eq(Merchant::getMerchantCode, payReg.getMerchantCode()));
        final MerchantPayReg one = this.getOne(new LambdaQueryWrapper<MerchantPayReg>().eq(MerchantPayReg::getChannelRegId, payReg.getChannelRegId()));
        Asserts.isTrue(one.getRegNextFlows().equals(MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION.getCode())
                || one.getRegNextFlows().equals(MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION_ING.getCode())
                || one.getRegNextFlows().equals(MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION_FAIL.getCode()), "商户当前节点不允许做对公账户验证！");
        accountVerifyRequest.setCompanyAccount(one.getBankAcctNo());
        accountVerifyRequest.setUmsRegId(one.getChannelRegId());

        //  调用渠道-申请对公打款验证
        merchantRegChannel.requestAccountVerify(accountVerifyRequest);
        updateMerchantRegFlows(one, MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION_ING, MerchantRegStatusEnums.INIT);
        RequestAccountVerifyResVO resVO = new RequestAccountVerifyResVO();
        resVO.setTradeMerchantPayRegId(payReg.getId());
        resVO.setMerchantCode(payReg.getMerchantCode());
        resVO.setCurrentFlow(MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION_ING.getCode());
        resVO.setNextFlow(merchantRegChannel.nextFlow(MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION_ING, MerchantTypeEnums.getByCode(Integer.parseInt(merchant.getMerchantType())).get()).getCode());
        merchantPayRegLogService.saveFlowLog(one.getId(), MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION_ING, MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION, 1);
        return resVO;
    }

    @Override
    public CompanyAccountVerifyResVO companyAccountVerify(RequestCompanyAccountVerifyRequest param) {
        final ApplicationInfo application = getApplication(param.getTermNo());
        final AbstractMerchantRegChannel merchantRegChannel = getPayChannel(application.getPaymentChannelCode());
        MerchantPayReg payReg = this.getById(param.getTradeMerchantPayRegId());
        Asserts.isTrue(null != payReg && Objects.nonNull(payReg.getId()), "商户进件记录不存在！");
        final Merchant merchant = merchantService.getOne(new LambdaQueryWrapper<Merchant>().eq(Merchant::getMerchantCode, payReg.getMerchantCode()));
        Asserts.isTrue(payReg.getRegCurrentFlows().equals(MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION_ING.getCode())
                || payReg.getRegCurrentFlows().equals(MerchantRegStatusEnums.SIGNING_IN_PROGRESS.getCode())
                || payReg.getRegCurrentFlows().equals(MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION_FAIL.getCode()), "商户当前节点不允许做对公账户验证！");
        final UmsMerchantReqCompanyAccountVerifyRequest companyAccountVerifyRequest = new UmsMerchantReqCompanyAccountVerifyRequest();
        final MerchantPayReg one = this.getOne(new LambdaQueryWrapper<MerchantPayReg>().eq(MerchantPayReg::getChannelRegId, payReg.getChannelRegId()));
        companyAccountVerifyRequest.setCompanyAccount(one.getBankAcctNo());
        companyAccountVerifyRequest.setUmsRegId(one.getChannelRegId());
        companyAccountVerifyRequest.setTransAmt(param.getTransAmt().toString());

        // 调用渠道-验证对公打款金额
        merchantRegChannel.companyAccountVerify(companyAccountVerifyRequest);
        updateMerchantRegFlows(one, MerchantRegStatusEnums.SIGNING_IN_PROGRESS, MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION_ING);
        CompanyAccountVerifyResVO resVO = new CompanyAccountVerifyResVO();
        resVO.setTradeMerchantPayRegId(payReg.getId());
        resVO.setMerchantCode(payReg.getMerchantCode());
        resVO.setCurrentFlow(MerchantRegStatusEnums.SIGNING_IN_PROGRESS.getCode());
        resVO.setNextFlow(merchantRegChannel.nextFlow(MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION_ING, MerchantTypeEnums.getByCode(Integer.parseInt(merchant.getMerchantType())).get()).getCode());
        if (merchantRegChannel.needSign()) {
            resVO.setNextFlow(merchantRegChannel.nextFlow(MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION_ING, MerchantTypeEnums.getByCode(Integer.parseInt(merchant.getMerchantType())).get()).getCode());
        } else {
            resVO.setNextFlow(MerchantRegStatusEnums.PROCESS_COMPLETED.getCode());
        }
        merchantPayRegLogService.saveFlowLog(one.getId(), MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION_SUCCESS, MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION_ING, 1);
        return resVO;
    }

    @Override
    public MerchantAgreementSignResVO agreementSign(MerchantPayRegAgreementSignRequest param) {
        final ApplicationInfo application = getApplication(param.getTermNo());
        final AbstractMerchantRegChannel merchantRegChannel = getPayChannel(application.getPaymentChannelCode());
        MerchantPayReg payReg = this.getById(param.getTradeMerchantPayRegId());
        Asserts.isTrue(null != payReg && Objects.nonNull(payReg.getId()), "商户进件记录不存在！");
        Asserts.isTrue(payReg.getRegCurrentFlows().equals(MerchantRegStatusEnums.SIGNING_IN_PROGRESS.getCode()) || payReg.getRegNextFlows().equals(MerchantRegStatusEnums.SIGNING_IN_PROGRESS.getCode()), "商户当前节点不允许做对签约操作！");
        AgreementSignSourceEnums agreementSignSourceEnums = AgreementSignSourceEnums.getByCode(param.getAgreementSignSource());
        Asserts.isTrue(null != agreementSignSourceEnums, "不支持的签约端类型！当前支持：PC、H5");
        final UmsMerchantReqAgreementSignRequest agreementSignRequest = new UmsMerchantReqAgreementSignRequest();
        agreementSignRequest.setUmsRegId(payReg.getChannelRegId());
        agreementSignRequest.setPcOrH5(param.getAgreementSignSource());

        // 发起签约之前先查询一把改商户是不是在审核中状态
        UmsMerchantReqStatusQueryRequest params = new UmsMerchantReqStatusQueryRequest();
        params.setUms_reg_id(payReg.getChannelRegId());
        MerchantRegStatusQueryResDTO dto = merchantRegChannel.queryRegisterStatus(params);
        log.info("查询商户进件状态结果：{}", dto.toString());
        Asserts.isTrue(!dto.getSourceApplyStatus().equals("01"), "商户正在签约中，请等待银行审核结果，不要重复发起！");
        Asserts.isTrue(!dto.getSourceApplyStatus().equals("02"), "商户正在入网审核中，请等待银行审核结果，不要重复发起！");
        Asserts.isTrue(!dto.getSourceApplyStatus().equals("03"), "商户入网成功，不要重复发起！");
        String signUrl = merchantRegChannel.agreementSign(agreementSignRequest);
        MerchantAgreementSignResVO resVO = new MerchantAgreementSignResVO();
        resVO.setTradeMerchantPayRegId(payReg.getId());
        resVO.setMerchantCode(payReg.getMerchantCode());
        resVO.setCurrentFlow(MerchantRegStatusEnums.SIGNING_IN_PROGRESS.getCode());
        resVO.setNextFlow(MerchantRegStatusEnums.PROCESS_COMPLETED.getCode());
        resVO.setSignUrl(signUrl);
        merchantPayRegLogService.saveFlowLog(payReg.getId(), MerchantRegStatusEnums.SIGNING_IN_PROGRESS, MerchantRegStatusEnums.CORPORATE_ACCOUNT_VERIFICATION_SUCCESS, 1);

        // 测试环境，模拟成功,一分钟后回调
        MerchantStatusMsg merchantStatusMsg = new MerchantStatusMsg();
        merchantStatusMsg.setMerchantCode(payReg.getMerchantCode());
        merchantStatusMsg.setMerchantPayRegId(payReg.getId());
        merchantStatusMsg.setApplyStatus(Integer.parseInt(MerchantApplyStatusEnums.success.getCode()));
        merchantStatusMsg.setApplySubStatus(MerchantApplySubStatusEnums.success.getCode());
        merchantStatusMsg.setChannelRegId(payReg.getChannelRegId());
        merchantStatusMsg.setMessageTime(LocalDateTime.now());
        merchantRegisterSender.sendMessage(merchantStatusMsg, 60 * 1000);
        return resVO;
    }

    @Override
    public List<MerchantChannelResponseDTO> queryOrgSubMerchant(List<Long> orgPaymentChannelId) {
        return this.getBaseMapper().queryOrgSubMerchant(orgPaymentChannelId);
    }

    @Override
    public List<MerchantChannelResponseDTO> listSubMerchant(List<MerchantChannelRequestDTO> params) {
        return this.getBaseMapper().querySubMerchant(params);
    }


    @Override
    public MerchantRegAllInfoRes queryRegisterMerchant(String shopLic, Long orgPaymentChannelId) {
        final List<Merchant> merchants = merchantService.list(new LambdaQueryWrapper<Merchant>().eq(Merchant::getShopLic, shopLic).eq(Merchant::getIsDelete, 0));
        if (CollectionUtils.isNotEmpty(merchants)) {
            final List<MerchantPayReg> list = this.list(new LambdaQueryWrapper<MerchantPayReg>().in(MerchantPayReg::getMerchantCode, merchants.stream().map(Merchant::getMerchantCode).collect(Collectors.toList())).eq(MerchantPayReg::getOrgPaymentChannelId, orgPaymentChannelId));
            if (CollectionUtils.isNotEmpty(list)) {
                return queryMerchantRegAllInfoRes(list.get(0).getId());
            }
        }
        return null;
    }

    @Override
    public MerchantRegAllInfoRes queryRegisterMerchant(Long regId) {
        return queryMerchantRegAllInfoRes(regId);
    }

    @Override
    public PageInfo<QueryMerchantRegResVO> findPageList(QueryMerchantRegReqVO queryMerchantRegReqVO) {
        IPage<MerchantPayReg> merchantPayRegPage = new Page<>();
        merchantPayRegPage.setCurrent(queryMerchantRegReqVO.getCurrentPage());
        merchantPayRegPage.setSize(queryMerchantRegReqVO.getPageSize());
        IPage<QueryMerchantRegResVO> pageResult = this.getBaseMapper().queryPage(merchantPayRegPage, queryMerchantRegReqVO);
        return new PageInfo<>(pageResult.getRecords(), new PageInfo.Pagination(pageResult.getCurrent(), (int) pageResult.getSize(), pageResult.getTotal()));
    }

    /**
     * 手工银行进件信息
     *
     * @param req
     */
    @Override
    public void manualSettingChannelInfo(ManualSettingChannelInfoReq req) {
        final MerchantPayReg merchantPayReg = this.getById(req.getId());
        if (null == merchantPayReg || Objects.isNull(merchantPayReg.getId())) {
            return;
        }
        Asserts.isNotNull(merchantPayReg, "未查询到进件记录");
        Asserts.isTrue(req.getApplyStatus().equals(1) || req.getApplyStatus().equals(2), "审核状态不正确！");
        MerchantPayReg update = new MerchantPayReg();
        update.setId(merchantPayReg.getId());
        if (req.getApplyStatus().equals(1)) {
            Asserts.isTrue(StringUtils.isNotEmpty(req.getChannelMerNo()), "请填写支付通道分配商户号！");
            update.setChannelMerNo(req.getChannelMerNo());
        }
        if (StringUtils.isNotEmpty(req.getCompanyNo())) {
            update.setCompanyNo(req.getCompanyNo());
        }
        update.setRegMode(0);
        update.setApplyStatus(req.getApplyStatus());
        update.setLastUpdDt(LocalDateTime.now());
        // 推送到业务系统
        if (StringUtils.isNotEmpty(merchantPayReg.getNotifyUrl())) {
            TradeMerchantStatusReq tradeMerchantStatusReq = new TradeMerchantStatusReq();
            tradeMerchantStatusReq.setTradeMerchantCode(merchantPayReg.getMerchantCode());
            tradeMerchantStatusReq.setTradeMerchantName("");
            tradeMerchantStatusReq.setRegCode(merchantPayReg.getRegCode());
            if (req.getApplyStatus().equals(1)) {
                tradeMerchantStatusReq.setTradeMerchantStatus(MerchantApplyStatusEnums.success.getCode());
                tradeMerchantStatusReq.setTradeMerchantStatusName(MerchantApplyStatusEnums.success.getMsg());
                tradeMerchantStatusReq.setTradeMerchantSubStatus(MerchantApplySubStatusEnums.success.getCode());
            } else {
                tradeMerchantStatusReq.setTradeMerchantStatus(MerchantApplyStatusEnums.final_error.getCode());
                tradeMerchantStatusReq.setTradeMerchantStatusName(MerchantApplyStatusEnums.final_error.getMsg());
                tradeMerchantStatusReq.setTradeMerchantSubStatus(MerchantApplySubStatusEnums.other.getCode());
            }
            notifyBusiness(merchantPayReg.getId(), tradeMerchantStatusReq);
        }
        this.updateById(update);
    }

    @Override
    public MerchantRegStatusQueryRes queryMerchantRegStatus(MerchantRegStatusQueryReqVO param) {
        MerchantPayReg merchantPayReg = this.getById(param.getTradeMerchantPayRegId());
        Asserts.isNotNull(merchantPayReg, "商户进件记录不存在！");
        MerchantRegStatusQueryRes result = new MerchantRegStatusQueryRes();
        result.setMerchantCode(merchantPayReg.getMerchantCode());
        result.setRegCode(merchantPayReg.getRegCode());
        result.setRegMode(merchantPayReg.getRegMode());
        result.setAuditErrorMsg(merchantPayReg.getAuditErrorMsg());
        result.setAuditErrorCode(merchantPayReg.getAuditErrorCode());
        result.setApplyStatus(merchantPayReg.getApplyStatus());
        result.setApplySubStatus(merchantPayReg.getApplySubStatus());
        if (merchantPayReg.getApplyStatus().equals(1) || merchantPayReg.getApplyStatus().equals(2)) {
            // 申请通过、申请失败
            result.setApplyStatusRemark(merchantPayReg.getApplyStatus().equals(1) ? "申请通过" : "申请失败");
            return result;
        }
        // 查询一下渠道测的状态
        final Merchant merchant = merchantService.getOne(new LambdaQueryWrapper<Merchant>().eq(Merchant::getMerchantCode, merchantPayReg.getMerchantCode()));
        BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(Objects.nonNull(merchant), "未查询到商户，请检查");
        final List<OrgBusiness> orgBusinesses = orgBusinessService.list(new LambdaQueryWrapper<OrgBusiness>().eq(OrgBusiness::getOrgPaymentChannelId, merchantPayReg.getOrgPaymentChannelId()));
        BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(CollectionUtils.isNotEmpty(orgBusinesses), "平台支付配置异常");
        final AbstractMerchantRegChannel merchantRegChannel = getPayChannel(orgBusinesses.get(0).getPaymentChannelCode());
        UmsMerchantReqStatusQueryRequest params = new UmsMerchantReqStatusQueryRequest();
        params.setUms_reg_id(merchantPayReg.getChannelRegId());
        final MerchantRegStatusQueryResDTO merchantRegStatusQueryRes = merchantRegChannel.queryRegisterStatus(params);
        // 修改商户进件状态
        MerchantApplyStatusEnums tradeMerchantStatus = MerchantApplyStatusEnums.getByCode(merchantRegStatusQueryRes.getApplyStatus()).get();
        MerchantApplySubStatusEnums subStatusEnums = MerchantApplySubStatusEnums.getByCode(merchantRegStatusQueryRes.getApplySubStatus()).get();
        // 更新商户进件状态
        ApplyStatusUpdateDTO updateDTO = new ApplyStatusUpdateDTO();
        updateDTO.setMerchantPayRegId(merchantPayReg.getId());
        updateDTO.setApplyStatusEnums(tradeMerchantStatus);
        updateDTO.setSubStatusEnums(subStatusEnums);
        updateDTO.setMerNo(merchantRegStatusQueryRes.getMerNo());
        updateDTO.setCompanyNo(merchantRegStatusQueryRes.getCompanyNo());
        applyStatusUpdate(updateDTO);
        // 通知业务端
        TradeMerchantStatusReq tradeMerchantStatusReq = new TradeMerchantStatusReq();
        tradeMerchantStatusReq.setTradeMerchantCode(merchantPayReg.getMerchantCode());
        tradeMerchantStatusReq.setTradeMerchantName("");
        tradeMerchantStatusReq.setRegCode(merchantPayReg.getRegCode());
        tradeMerchantStatusReq.setTradeMerchantStatus(tradeMerchantStatus.getCode());
        tradeMerchantStatusReq.setTradeMerchantSubStatus(subStatusEnums.getCode());
        tradeMerchantStatusReq.setTradeMerchantStatusName(tradeMerchantStatus.getMsg());
        notifyBusiness(merchantPayReg.getId(), tradeMerchantStatusReq);
        return result;
    }

    /**
     * 设置商户清分规则
     *
     * @param ruleReqVO 规则信息
     */
    @Override
    public void setSettleRule(MerchantPayRegSettleRuleReqVO ruleReqVO) {
        final ApplicationInfo application = getApplication(ruleReqVO.getTermNo());
        MerchantPayReg one = this.getOne(new LambdaQueryWrapper<MerchantPayReg>().eq(MerchantPayReg::getMerchantCode, ruleReqVO.getMerchantCode()).eq(MerchantPayReg::getOrgPaymentChannelId, application.getOrgPaymentChannelId()));
        Asserts.isNotNull(one, "未查询到商户进件记录");
        MerchantSettleRule rule = new MerchantSettleRule();
        rule.setMerchantCode(ruleReqVO.getMerchantCode());
        rule.setOrgPaymentChannelId(one.getOrgPaymentChannelId());
        rule.setPlatformPercent(ruleReqVO.getPlatformPercent());
        rule.setCycleType(ruleReqVO.getCycleType());
        rule.setCycleValue(ruleReqVO.getCycleValue());
        merchantSettleRuleService.addRule(rule);
    }

    @Override
    public List<MerchantPayRegFileResVO> queryFileList(List<Long> fileIds) {
        return merchantPayRegFileService.list(new LambdaQueryWrapper<MerchantPayRegFile>().in(MerchantPayRegFile::getId, fileIds)).stream().map(item -> {
            MerchantPayRegFileResVO vo = new MerchantPayRegFileResVO();
            vo.setId(item.getId());
            vo.setFileId(item.getFileId());
            vo.setFilePath(item.getFilePath());
            vo.setInnerFilePath(item.getInnerFilePath());
            vo.setFileSize(item.getFileSize());
            vo.setFileName(item.getDocumentName());
            vo.setDocumentType(item.getDocumentType());
            vo.setFileType(item.getFileType());
            return vo;
        }).toList();
    }

    @Override
    public MerchantRegNotifyRes notifyHandler(Map<String, Object> params, PaymentChannelEnum paymentChannel) {
        if (Objects.isNull(params) || params.size() == 0) {
            log.warn("支付渠道侧商户进件回调参数为空");
            return null;
        }

        AbstractMerchantRegChannel payChannel = getPayChannel(paymentChannel.getCode());
        ChannelNotifyMessage channelNotifyMessage = payChannel.callbackMsg(params);
        Asserts.isTrue(null != channelNotifyMessage && MapUtils.isNotEmpty(channelNotifyMessage.getMessageBody()), "支付渠道回调消息为空");
        Map<String, Object> messageBody = channelNotifyMessage.getMessageBody();

        MerchantRegNotifyRes notifyRes = new MerchantRegNotifyRes();
        Map<String, Object> obj = null;
        switch (paymentChannel) {
            case UMS:
                // 银商支付通道
                obj = handleUmsMsgAndNotifyBusiness(messageBody);
                break;
            case gao_cheng_nong_hang:
                // 高诚农行支付通道
                obj = handlerGcMsg(messageBody);
                break;
            default:
                log.error("当前不支持的支付通道！");
        }

        notifyRes.setSuccess(null != obj);
        notifyRes.setResponseData(obj);
        return notifyRes;
    }

    public Map<String, Object> handlerGcMsg(Map<String, Object> messageBody) {
        // 进件申请提交的申请单号
        String applyNo = MapUtils.getString(messageBody, "applyNo");
        // 节点：1 - 初审 2 - 复核
        Integer step = MapUtils.getInteger(messageBody, "step");
        // 状态：1 - 审批通过 2 - 驳回
        Integer status = MapUtils.getInteger(messageBody, "status");
        // 审批备注
        String remark = MapUtils.getString(messageBody, "remark");

        MerchantPayReg merchantPayReg = queryByChannelRegId(applyNo);
        if (merchantPayReg == null) {
            log.error("高诚商户进件回调未查询到进件记录！");
            return null;
        }

        MerchantApplyStatusEnums tradeMerchantStatus = MerchantApplyStatusEnums.ing;
        MerchantApplySubStatusEnums subStatusEnums = MerchantApplySubStatusEnums.ing;
        Map<String, Object> result = new HashMap<>();
        if (step.equals(1)) {
            //初审:附件上传确认（接口）后进入初审
            if (status == 1) {
                // 审批通过
                tradeMerchantStatus = MerchantApplyStatusEnums.ing;
                subStatusEnums = MerchantApplySubStatusEnums.ing;
            } else {
                // 审批不通过
                // 入网失败，最终失败
                tradeMerchantStatus = MerchantApplyStatusEnums.final_error;
                subStatusEnums = MerchantApplySubStatusEnums.final_error;
            }
        } else {
            // 复核：商户验证完成后进入复核，复核完成后流程结束
            if (status == 1) {
                // 审批通过
                tradeMerchantStatus = MerchantApplyStatusEnums.success;
                subStatusEnums = MerchantApplySubStatusEnums.success;
            } else {
                // 审批不通过
                // 入网失败，最终失败
                tradeMerchantStatus = MerchantApplyStatusEnums.final_error;
                subStatusEnums = MerchantApplySubStatusEnums.final_error;
            }
        }
        if (tradeMerchantStatus == MerchantApplyStatusEnums.success
                || tradeMerchantStatus == MerchantApplyStatusEnums.final_error) {
            // 最终审核通过，修改商户进件状态状态
            // 修改商户进件状态
            ApplyStatusUpdateDTO updateDTO = new ApplyStatusUpdateDTO();
            updateDTO.setMerchantPayRegId(merchantPayReg.getId());
            updateDTO.setApplyStatusEnums(tradeMerchantStatus);
            updateDTO.setSubStatusEnums(subStatusEnums);
            applyStatusUpdate(updateDTO);
            // 通知业务端
            TradeMerchantStatusReq tradeMerchantStatusReq = new TradeMerchantStatusReq();
            tradeMerchantStatusReq.setTradeMerchantCode(merchantPayReg.getMerchantCode());
            tradeMerchantStatusReq.setTradeMerchantName("");
            tradeMerchantStatusReq.setRegCode(merchantPayReg.getRegCode());
            tradeMerchantStatusReq.setTradeMerchantStatus(tradeMerchantStatus.getCode());
            tradeMerchantStatusReq.setTradeMerchantSubStatus(subStatusEnums.getCode());
            tradeMerchantStatusReq.setTradeMerchantStatusName(tradeMerchantStatus.getMsg());
            notifyBusiness(merchantPayReg.getId(), tradeMerchantStatusReq);
        }
        return result;
    }

    public Map<String, Object> handleUmsMsgAndNotifyBusiness(Map<String, Object> messageBody) {
        if (messageBody.containsKey("ums_reg_id")) {
            // 银联渠道回调
            /**
             * 00：签约中
             * 01：签约成功
             * 02：入网审核中
             * 03：入网成功
             * 04：入网失败
             * 05：对公账户待验证或异常
             * 06：风控审核中
             * 28：资料验证失败
             * 31：冻结账户
             * 99：其它错误
             */
            String applyStatus = MapUtils.getString(messageBody, "apply_status");
            // 银联进件流水号
            String umsRegId = MapUtils.getString(messageBody, "ums_reg_id");
            // 银联支付商户号
            String merNo = MapUtils.getString(messageBody, "mer_no");
            String companyNo = MapUtils.getString(messageBody, "company_no");
            //商户多应用信息
            Object mappInfoList = messageBody.get("mapp_info_list");
            if (!Objects.isNull(mappInfoList)) {
                Map<String, Object> stringObjectMap = JsonUtil.fromJson(mappInfoList, new TypeReference<Map<String, Object>>() {
                });
                if (MapUtils.isNotEmpty(stringObjectMap) && stringObjectMap.containsKey("mapp_no") && StringUtils.isNotEmpty(MapUtils.getString(stringObjectMap, "mapp_no"))) {
                    companyNo = MapUtils.getString(stringObjectMap, "mapp_no");
                }
            }
            MerchantPayReg merchantPayReg = queryByChannelRegId(umsRegId);
            if (merchantPayReg == null) {
                log.error("银联商户进件回调未查询到进件记录！");
                return null;
            }
            merchantPayReg.setApplySubStatus(applyStatus);

            MerchantApplyStatusEnums tradeMerchantStatus = MerchantApplyStatusEnums.ing;
            MerchantApplySubStatusEnums subStatusEnums = MerchantApplySubStatusEnums.ing;

            switch (applyStatus) {
                case "00", "01", "02", "34" -> {
                    // 签约中
                    tradeMerchantStatus = MerchantApplyStatusEnums.ing;
                    subStatusEnums = MerchantApplySubStatusEnums.ing;
                }
                case "03" -> {
                    // 入网成功
                    tradeMerchantStatus = MerchantApplyStatusEnums.success;
                    subStatusEnums = MerchantApplySubStatusEnums.success;
                }
                case "04" -> {
                    // 入网失败，最终失败
                    tradeMerchantStatus = MerchantApplyStatusEnums.final_error;
                    subStatusEnums = MerchantApplySubStatusEnums.final_error;
                }
                default -> {
                    // 其他失败
                    tradeMerchantStatus = MerchantApplyStatusEnums.exception;
                    switch (applyStatus) {
                        case "05" -> subStatusEnums = MerchantApplySubStatusEnums.dgzh_yc;
                        case "28" -> subStatusEnums = MerchantApplySubStatusEnums.zlyz_yc;
                        default -> subStatusEnums = MerchantApplySubStatusEnums.other;
                    }
                }

            }
            // 修改商户进件状态
            ApplyStatusUpdateDTO updateDTO = new ApplyStatusUpdateDTO();
            updateDTO.setMerchantPayRegId(merchantPayReg.getId());
            updateDTO.setApplyStatusEnums(tradeMerchantStatus);
            updateDTO.setSubStatusEnums(subStatusEnums);
            updateDTO.setMerNo(merNo);
            updateDTO.setCompanyNo(companyNo);
            applyStatusUpdate(updateDTO);
            // 通知业务端
            TradeMerchantStatusReq tradeMerchantStatusReq = new TradeMerchantStatusReq();
            tradeMerchantStatusReq.setTradeMerchantCode(merchantPayReg.getMerchantCode());
            tradeMerchantStatusReq.setTradeMerchantName("");
            tradeMerchantStatusReq.setRegCode(merchantPayReg.getRegCode());
            tradeMerchantStatusReq.setTradeMerchantStatus(tradeMerchantStatus.getCode());
            tradeMerchantStatusReq.setTradeMerchantSubStatus(subStatusEnums.getCode());
            tradeMerchantStatusReq.setTradeMerchantStatusName(tradeMerchantStatus.getMsg());
            notifyBusiness(merchantPayReg.getId(), tradeMerchantStatusReq);
            Map<String, Object> result = new HashMap<>();
            result.put("res_code", "0000");
            return result;
        } else {
            log.error("支付渠道侧商户进件回调，不支持的支付通道消息");
            return null;
        }
    }

    @Override
    public void deleteFile(String fileId) {
        MerchantPayRegFile regFile = merchantPayRegFileService.getById(Long.parseLong(fileId));
        if (null != regFile) {
            MerchantPayReg merchantPayReg = this.getById(regFile.getMerchantPayRegId());
            if (Objects.isNull(merchantPayReg)) {
                // 还没有提交保存，直接删除文件记录
                merchantPayRegFileService.removeById(regFile.getId());
                return;
            }
            Asserts.isTrue(!merchantPayReg.getApplyStatus().equals(1), "商户当前状态不允许删除证件材料！");
            merchantPayRegFileService.removeById(regFile.getId());
        }
    }

    @Override
    public List<QueryMccRes> queryMcc(MerchantRegQueryMccReqVO params) {
        final ApplicationInfo application = getApplication(params.getTermNo());
        return industryService.queryMcc(params.getMccName(), application.getPaymentChannelCode());
    }

    @Override
    public List<QueryMccRes> queryMccByCode(MerchantRegQueryMccReqVO params) {
        return industryService.queryMccByCode(params.getMccName(), params.getMccCode());
    }

    @Override
    public void smsSend(MerchantRegSendSmsReqVO params) {
        MerchantPayReg merchantPayReg = this.getById(params.getTradeMerchantPayRegId());
        Asserts.isTrue(merchantPayReg != null, "未查询到商户进件信息");
        final ApplicationInfo application = getApplication(params.getTermNo());

        BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(Objects.nonNull(application), "应用未被授权交易！");
        final List<OrgBusiness> orgBusinesses = orgBusinessService.list(new LambdaQueryWrapper<OrgBusiness>().eq(OrgBusiness::getClientId, application.getClientId()).eq(OrgBusiness::getOrgPaymentChannelId, application.getOrgPaymentChannelId()));
        BusinessErrorInfoEnum.MERCHANT_REG_BUSINESS_ERROR.assertNotEmpty(orgBusinesses);
        final AbstractMerchantRegChannel merchantRegChannel = getPayChannel(orgBusinesses.get(0).getPaymentChannelCode());
        MerchantRegSmsSendBO merchantRegSmsSendBO = new MerchantRegSmsSendBO();
        merchantRegSmsSendBO.setOrgPaymentChannelId(orgBusinesses.get(0).getOrgPaymentChannelId());
        // 渠道签约id
        merchantRegSmsSendBO.setChannelRegNo(merchantPayReg.getChannelRegId());
        merchantRegChannel.smsSend(merchantRegSmsSendBO);

    }

    @Override
    public void smsVerify(MerchantRegSmsVerifyReqVO params) {
        MerchantPayReg merchantPayReg = this.getById(params.getTradeMerchantPayRegId());
        Asserts.isTrue(merchantPayReg != null, "未查询到商户进件信息");
        final ApplicationInfo application = getApplication(params.getTermNo());

        BusinessErrorInfoEnum.SYSTEM_ERROR.assertIsTrue(Objects.nonNull(application), "应用未被授权交易！");
        final List<OrgBusiness> orgBusinesses = orgBusinessService.list(new LambdaQueryWrapper<OrgBusiness>().eq(OrgBusiness::getClientId, application.getClientId()).eq(OrgBusiness::getOrgPaymentChannelId, application.getOrgPaymentChannelId()));
        BusinessErrorInfoEnum.MERCHANT_REG_BUSINESS_ERROR.assertNotEmpty(orgBusinesses);
        final AbstractMerchantRegChannel merchantRegChannel = getPayChannel(orgBusinesses.get(0).getPaymentChannelCode());
        MerchantRegSmsVerifyBO merchantRegSmsVerifyBO = new MerchantRegSmsVerifyBO();
        merchantRegSmsVerifyBO.setOrgPaymentChannelId(orgBusinesses.get(0).getOrgPaymentChannelId());
        // 短信验证码
        merchantRegSmsVerifyBO.setSmsCode(params.getVerificationCode());
        merchantRegChannel.smsVerify(merchantRegSmsVerifyBO);
    }

    private void applyStatusUpdate(ApplyStatusUpdateDTO updateDTO) {
        MerchantPayReg updateMerchant = new MerchantPayReg();
        updateMerchant.setId(updateDTO.getMerchantPayRegId());
        updateMerchant.setApplySubStatus(updateDTO.getSubStatusEnums().getCode());
        updateMerchant.setLastUpdDt(LocalDateTime.now());
        updateMerchant.setApplyStatus(Integer.parseInt(updateDTO.getApplyStatusEnums().getCode()));
        updateMerchant.setChannelMerNo(updateDTO.getMerNo());
        updateMerchant.setCompanyNo(updateDTO.getCompanyNo());
        switch (updateDTO.getApplyStatusEnums()) {
            case ing -> {
                // 如果此时还是申请中的状态，只更新本地记录即可
                updateMerchant.setIsDelete(0);
                this.updateById(updateMerchant);
            }
            case success -> {
                // 如果此时还是申请中的状态，只更新本地记录即可
                updateMerchant.setIsDelete(0);
                updateMerchant.setApplySubStatus(MerchantApplySubStatusEnums.success.getCode());
                this.updateById(updateMerchant);
            }
            case final_error -> {
                // 流程失败
                updateMerchant.setApplySubStatus(updateDTO.getSubStatusEnums().getCode());
                updateMerchant.setDeleteStatus(1);
                this.updateById(updateMerchant);
            }
            case exception -> {
                // 有步骤异常，但总流程不终结，修复后继续
                updateMerchant.setApplySubStatus(updateDTO.getSubStatusEnums().getCode());
                updateMerchant.setDeleteStatus(0);
                this.updateById(updateMerchant);
            }
        }
    }

    private MerchantPayReg queryByChannelRegId(String channelRegId) {
        return this.getOne(new LambdaQueryWrapper<MerchantPayReg>().eq(MerchantPayReg::getChannelRegId, channelRegId));
    }

    public void notifyBusiness(Long merchantPayRegId, TradeMerchantStatusReq tradeMerchantStatusReq) {
        MerchantPayReg merchantPayReg = this.getById(merchantPayRegId);
        final String s = ForestHttpUtil.getInstance().doPostJson(merchantPayReg.getNotifyUrl(), tradeMerchantStatusReq, new BasicHeader[]{new BasicHeader("content-type", "application/json")});
        Asserts.isNotBlank(s, "回调业务系统异常！");
        final JSONObject jsonObject = JSONObject.parseObject(s);
        Asserts.isTrue(null != jsonObject && jsonObject.getInteger("ret") == 0, "回调业务系统异常！");
    }

    /**
     * 获取支付渠道处理器
     *
     * @param paymentChannelCode
     * @return
     */
    private AbstractMerchantRegChannel getPayChannel(String paymentChannelCode) {
        if (paymentChannelCode.startsWith("ums")) {
            paymentChannelCode = PaymentChannelEnum.UMS.getCode();
        }
        // 上传文件到银联
        return PayChannelFactory.get(paymentChannelCode);
    }

    private boolean updateMerchantRegFlows(MerchantPayReg one, MerchantRegStatusEnums currentFlow, MerchantRegStatusEnums nextFlow) {
        final MerchantPayReg merchantPayReg = new MerchantPayReg();
        merchantPayReg.setId(one.getId());
        merchantPayReg.setRegCurrentFlows(currentFlow.getCode());
        merchantPayReg.setRegNextFlows(nextFlow.getCode());
        merchantPayReg.setLastUpdDt(LocalDateTime.now());
        return this.updateById(merchantPayReg);
    }
}
